package com.ruoyi.activity.task;

import com.ruoyi.activity.domain.CouponActivity;
import com.ruoyi.activity.domain.Product;
import com.ruoyi.activity.mapper.CouponActivityMapper;
import com.ruoyi.activity.mapper.ProductMapper;
import com.ruoyi.activity.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 活动定时上下线任务
 */
@Component
@Slf4j
public class ActivityStatusTask {

    @Autowired
    private CouponActivityMapper activityMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ProductMapper productMapper;
    /**
     * 每分钟检查活动状态，自动上下线
     */
    @Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
    public void updateActivityStatus() {
        // 获取当前时间
        Date now = new Date();
        // 查询所有活动
        List<CouponActivity> activities = activityMapper.selectList(null);
        for (CouponActivity activity : activities) {
            // 如果活动未开始且到达开始时间，设置为进行中
            if (activity.getStatus() == 0 && now.after(activity.getStartTime())) {
                activity.setStatus(1);

                activityMapper.updateById(activity);
                redisTemplate.opsForValue().set("coupon:activity:" + activity.getId() + ":stock", activity.getTotalCount());
            }
            // 如果活动进行中且到达结束时间，设置为已结束
            if (activity.getStatus() == 1 && now.after(activity.getEndTime())) {
                activity.setStatus(2);
                activityMapper.updateById(activity);
            }
        }
    }
    // Redis中存储订单超时键的模式
    private static final String ORDER_EXPIRE_PREFIX = "order:expire:*";

    /**
     * 每分钟执行一次订单超时检查
     */
    @Scheduled(fixedRate = 60_000) // 60秒 = 1分钟
    public void checkAndCancelTimeoutOrders() {
        try {
            log.info("开始扫描超时订单...");

            // 1. 扫描所有超时订单键
            Set<String> expireKeys = redisTemplate.keys(ORDER_EXPIRE_PREFIX);
            if (expireKeys == null || expireKeys.isEmpty()) {
                log.info("未发现超时订单");
                return;
            }

            int canceledCount = 0;
            int errorCount = 0;

            // 2. 处理每个超时订单
            for (String key : expireKeys) {
                try {
                    // 从键名中提取订单ID (格式: order:expire:12345)
                    String[] parts = key.split(":");
                    if (parts.length < 3) continue;

                    Long orderId = Long.parseLong(parts[2]);

                    // 3. 检查键是否仍然存在（防止重复处理）
                    if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
                        continue;
                    }

                    // 4. 尝试获取键的剩余时间
                    Long ttl = redisTemplate.getExpire(key, TimeUnit.SECONDS);

                    // 5. 如果键已过期（ttl <= 0）或接近过期
                    if (ttl != null && ttl <= 10) { // 10秒内过期
                        // 6. 尝试取消订单（系统自动取消）
                        boolean success = orderService.cancelOrder(null, orderId);

                        if (success) {
                            log.info("成功取消超时订单: orderId={}", orderId);
                            canceledCount++;
                        } else {
                            log.warn("取消超时订单失败: orderId={}", orderId);
                        }
                    }
                } catch (NumberFormatException e) {
                    log.error("订单ID格式错误: key={}", key, e);
                    errorCount++;
                } catch (Exception e) {
                    log.error("处理超时订单异常: key={}", key, e);
                    errorCount++;
                }
            }

            log.info("超时订单扫描完成: 共处理{}个订单, 成功取消{}个, 错误{}个",
                    expireKeys.size(), canceledCount, errorCount);
        } catch (Exception e) {
            log.error("订单超时任务执行失败", e);
        }
    }
    // 服务启动时初始化所有商品库存
    @PostConstruct
    public void initProductStocks() {
        List<Product> products = productMapper.selectList(null);
        for (Product product : products) {
            String stockKey = "stock:product:" + product.getId();
            if (!redisTemplate.hasKey(stockKey)) {
                redisTemplate.opsForValue().set(stockKey, product.getStock());
            }
        }
    }


} 